/*
 * @Author: 江舟 jijiangzhou@recycloud.cn
 * @Date: 2024-03-22 15:55:39
 * @LastEditors: 江舟 jijiangzhou@recycloud.cn
 * @LastEditTime: 2024-08-08 10:18:24
 * @FilePath: \vite-project\src\components\common\FileUploader.tsx
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */

import { Icon } from '@iconify/react/dist/iconify.js';
import { Spin, type UploadProps, Upload, UploadFile, message, Button, Image } from 'antd';
import { useEffect, useState } from 'react';
import { Uploder, getFileType, getImageAndFileType } from 'utils/helper';
import { ocrBankslipFromOss, ocrInvoiceFromOss } from 'apis/common';
import { Base64 } from 'js-base64';

interface ImageUploadPops {
    value?: UploadFile[];
    onChange?: (files?: UploadFile[]) => void;
    tooltip?: string;
    ocrType?:
        | 'ocrInvoiceFromOss' // 发票
        | 'ocrBankslipFromOss'; // 银行回单
    onOcrSuccess?: (res: any) => void;
    showUploadList?: object | boolean;
    defaultAccept?: string;
}

export type UploadFileType = UploadFile & {
    attachId: string;
    filePath: string;
};

const FileUpload: React.FC<ImageUploadPops & UploadProps> = ({
    tooltip = '类型不是图片或pdf，请重新上传',
    value,
    onChange,
    accept = 'image/*,application/pdf',
    ocrType,
    onOcrSuccess,
    showUploadList = {
        showPreviewIcon: true,
        showRemoveIcon: true,
        showDownloadIcon: true,
    },
    defaultAccept = '',
    ...rest
}) => {
    const [loading, setLoading] = useState(false);
    const isImageFile = (file: UploadFile) => {
        if (
            (file?.type?.includes('image') && accept.includes('image/*')) ||
            (file?.type?.includes('image') && defaultAccept.includes('image/*'))
        ) {
            return true;
        }
        if (defaultAccept?.includes('ofd') && file?.type?.includes('ofd')) {
            // 判断ofd文件
            return true;
        }
        return accept.includes(file?.type) || defaultAccept.includes(file?.type);
    };
    const [currentList, setCurrentList] = useState<UploadFile[]>(value || []);
    const beforeUpload = (file: UploadFile) => {
        const isImage = isImageFile(file);
        if (!isImage) {
            message.error(`${file.name}${tooltip}`);
        }
        return isImage || Upload.LIST_IGNORE;
    };
    const ocrFunc = async (attachId: string) => {
        if (ocrType) {
            switch (ocrType) {
                case 'ocrInvoiceFromOss': {
                    // 发票
                    ocrInvoiceFromOss({
                        attachId,
                    })
                        .then((res) => {
                            onOcrSuccess?.(res);
                            message.success('识别成功');
                        })
                        .catch((error) => {
                            message.error('识别失败');
                        });
                    break;
                }
                case 'ocrBankslipFromOss': {
                    // 银行回单
                    ocrBankslipFromOss({
                        attachId,
                    })
                        .then((res) => {
                            onOcrSuccess?.(res);
                            message.success('识别成功');
                        })
                        .catch(() => {
                            message.error('识别失败');
                        });
                    break;
                }
            }
        }
    };
    const customRequest: any = async ({
        file,
        onSuccess,
        onError,
    }: {
        file: UploadFileType;
        onSuccess: any;
        onError: any;
    }) => {
        setLoading(true);
        try {
            let { authQueryFileUrl, attachId, filePath } = await Uploder(file);
            file.attachId = attachId;
            file.url = authQueryFileUrl;
            file.filePath = filePath;
            ocrFunc?.(attachId);
            onSuccess(file);
        } catch (error) {
            onError(new Error('上传失败'));
        } finally {
            setLoading(false);
        }
    };
    const onUploadChange: ({ file, fileList }: { file: UploadFile; fileList: UploadFile[] }) => void = ({
        file,
        fileList,
    }) => {
        setCurrentList(fileList);
        let uploadComplete = true;
        for (let i = 0; i < fileList.length; i++) {
            if (fileList[i].status === 'uploading') {
                uploadComplete = false;
                break;
            }
        }
        if (!uploadComplete) {
            return;
        }
        const list = fileList.filter((item) => item.status === 'done');
        onChange?.(list);
    };

    const [visible, setVisible] = useState(false);
    const [previewUrl, setPreviewUrl] = useState('');
    const onPreview = (file: UploadFile) => {
        if (getImageAndFileType(file.url || '') !== 'images') {
            const previweSrc = `${
                import.meta.env.VITE_NODE_ENV === 'prod' ? '' : 'http://10.20.1.250:82'
            }/fileview/onlinePreview?url=${encodeURIComponent(Base64.encode(file.url))}`;
            window.open(previweSrc);
            return;
        }
        if (file.thumbUrl || file.url) {
            setPreviewUrl(file.url || file.thumbUrl || '');
            setVisible(true);
        }
    };

    const uploadButton = (
        <Spin spinning={loading}>
            <Button type='primary'>
                {!loading ? <Icon icon='ant-design:plus-outlined' /> : null}
                上传
            </Button>
        </Spin>
    );

    useEffect(() => {
        if (currentList?.length === 0) {
            setCurrentList(value || []);
        }
    }, [value]);
    return (
        <>
            <Upload
                fileList={currentList}
                accept={accept}
                listType='picture'
                beforeUpload={beforeUpload}
                customRequest={customRequest}
                onChange={onUploadChange}
                isImageUrl={(file) => {
                    return getImageAndFileType(file.url || '') === 'images';
                }}
                iconRender={(file) => {
                    if (file.status === 'uploading') {
                        return <Spin size='small' className='block flex items-center justify-center w-48px h-48px' />;
                    }
                    let type = getFileType(file.url || '');
                    return {
                        pdf: <Icon className='text-red text-24px' icon='ant-design:file-pdf-outlined' />,
                    }[type];
                }}
                onPreview={onPreview}
                showUploadList={showUploadList}
                {...rest}
            >
                {(currentList?.length || 0) < (rest?.maxCount || 0) &&
                (!value || value?.length < (rest?.maxCount || 0)) &&
                !loading
                    ? uploadButton
                    : showUploadList === false
                    ? uploadButton
                    : null}
            </Upload>
            <Image
                width={200}
                style={{ display: 'none' }}
                src={previewUrl}
                preview={{
                    visible,
                    src: previewUrl,
                    onVisibleChange: (value: any) => {
                        setVisible(value);
                    },
                }}
            />
        </>
    );
};

export default FileUpload;
